package com.dfhc.util;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;

import com.dfhc.ISystemConstant;

import sun.misc.BASE64Decoder;



/**
 * 加密及解密工具
 * @author longseb
 *
 */
public class CryptoHelper {
	//
	/**
	 * 解密过程，先用Base64进行解密，然后再用3DES进行第二次解密，得到明文
	 * 
	 * @param src 明文
	 * @param key 密钥
	 * @param charSet 字符集
	 */
	public static String decryptThreeDESECB(String src,String key,String charSet) throws Exception {
		DESedeKeySpec dks = new DESedeKeySpec(key.getBytes(charSet));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
		SecretKey securekey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DESede");
		cipher.init(Cipher.DECRYPT_MODE, securekey);
		byte[] retByte = cipher.doFinal(Base64.decodeBase64(src.getBytes(charSet)));
		return new String(retByte,charSet); 
	}
	
	/**
	 * 加密过程，先用3DES进行加密，然后再用Base64进行第二次加密输出，得到密文 
	 * @param encodeByte 密文
	 * @param key 密钥
	 * @param charset 字符集
	 */
	public static String encryptThreeDESECBBYTE(String src,String key,String charSet) throws Exception {
		DESedeKeySpec dks = new DESedeKeySpec(key.getBytes(charSet));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
		SecretKey securekey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DESede");
		cipher.init(Cipher.ENCRYPT_MODE, securekey);
//		byte[] retByte = cipher.doFinal(encodeByte);		
		byte[] retByte = cipher.doFinal(Base64.encodeBase64(src.getBytes(charSet)));
		return new String(retByte,charSet); 
	}
	 /** 
     * 3DESECB加密  
     * @param src 要进行了加密的原文 
     * @param key 密钥   key必须是长度大于等于 3*8 = 24 位 
     * @return 
     * @throws Exception 
     */  
    public static String encryptThreeDESECB(String src,String key) throws Exception  
    {  
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");  
        SecretKey securekey = keyFactory.generateSecret(dks);  
          
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, securekey);  
        byte[] b=cipher.doFinal(src.getBytes());  
          
        return Base64.encodeBase64String(b);  
          
    }  
    /** 
     * 3DESECB解密 
     * @param src 要解密的密文字符 
     * @param key 解密的Key key必须是长度大于等于 3*8 = 24 位 
     * @return 
     * @throws Exception 
     */  
    public static String decryptThreeDESECB(String src,String key) throws Exception  
    {  
    	   //--通过base64,将字符串转成byte数组  
        BASE64Decoder decoder = new BASE64Decoder();  
        byte[] bytesrc = decoder.decodeBuffer(src);  
        //--解密的key  
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");  
        SecretKey securekey = keyFactory.generateSecret(dks);  
          
        //--Chipher对象解密  
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");  
        cipher.init(Cipher.DECRYPT_MODE, securekey);  
        byte[] retByte = cipher.doFinal(bytesrc);  
          
        return new String(retByte,"utf-8");  
    } 
    /**
     * 加密 url
     * @param request 请求
     * @param url 明文url
     * @return 密文url
     * @throws Exception
     */
    public static String encryptUrl(HttpServletRequest request,String url) throws Exception{
    	String key = (String) request.getSession().getAttribute(ISystemConstant.ENCRYPT_URL_KEY);
    	HttpSession session = request.getSession();
    	
    	if(StringHelper.isEmpty(key)){
    		throw new Exception("加密url key为空!Session已过期或尚未登录!");
    	}
    	if(StringHelper.isEmpty(url)){
    		throw new Exception("url为空!");
    	}
    	Map<String,Object> sessionkey = (Map<String,Object>) request.getSession().getAttribute(ISystemConstant.ENCRYPT_URL_SESSIONKEY);
    	String encryptThreeDESECB =null;
    	if(sessionkey!=null){
    		String encrypurl = (String)sessionkey.get(url);
			if(!StringHelper.isEmpty(encrypurl)){
				encryptThreeDESECB =encrypurl;
			}else{
				encryptThreeDESECB ="/"+encryptThreeDESECB(url, key);
				sessionkey.put(url, encryptThreeDESECB);
			}
    	}else{
    		Map<String,Object> maps = new HashMap<String,Object>();
    		encryptThreeDESECB = "/"+encryptThreeDESECB(url, key);
    		maps.put(url, encryptThreeDESECB);
    		session.setAttribute(ISystemConstant.ENCRYPT_URL_SESSIONKEY, maps);
    	}
    	
    	return encryptThreeDESECB;
    }
    /**
     * 解密url
     * @param request
     * @param encryptUrl 密文url
     * @return
     * @throws Exception
     */
    public static String decryptUrl(HttpServletRequest request,String encryptUrl) throws Exception{
    	String key = (String) request.getSession().getAttribute(ISystemConstant.ENCRYPT_URL_KEY);
    	HttpSession session = request.getSession();
    	if(StringHelper.isEmpty(key)){
    		throw new Exception("加密 url key为空!Session已过期或尚未登录!");
    	}
    	if(StringHelper.isEmpty(encryptUrl)){
    		throw new Exception("url为空!");
    	}
    	
    	Map<String,Object> sessionkey = (Map<String,Object>) request.getSession().getAttribute(ISystemConstant.DECRYPT_URL_SESSIONKEY );
    	String decryptThreeDESECB =null;
    	if(sessionkey!=null){
    		String encrypurl = (String)sessionkey.get(encryptUrl);
			if(!StringHelper.isEmpty(encrypurl)){
				decryptThreeDESECB =encrypurl;
			}else{
				decryptThreeDESECB ="/"+decryptThreeDESECB(encryptUrl, key);
				sessionkey.put(encryptUrl, decryptThreeDESECB);
			}
    	}else{
    		Map<String,Object> maps = new HashMap<String,Object>();
    		decryptThreeDESECB = "/"+decryptThreeDESECB(encryptUrl, key);
    		maps.put(encryptUrl, decryptThreeDESECB);
    		session.setAttribute(ISystemConstant.DECRYPT_URL_SESSIONKEY , maps);
    	}
    	
    	return decryptThreeDESECB;

    }
    public static void main(String[] args) {
    	try {
    		String date="{\"app_version\":\"1.0.0\",\"reqType\":\"10101\",\"key\":\"CIP80101JYTX\",\"userPassword\":\"bbb\",\"userName\":\"aaa\"}";
    		String des3 = "ax2Jov7XPkfq5bncyInYFwSoIfUfE6npLraTS6K377V+kqC6YI57VaqbLTMjlKR75FfgMmdyOkeESxxS5woSmBjQj6xCDmLAU8w+0m0cvwHaLdYlYS0FeQqVW6iZD5VMlAJF6q42LPw=";
    		String key = "ea61504510763594a4bd5-31";
    		String md5 = "29f8f3ba93560db532eeabd45498bc38";
    		System.out.println(decryptThreeDESECB(des3,key));
    		if(decryptThreeDESECB(des3,key).equals(date)){
    			System.out.println("解密成功");
    		}
    		System.out.println(MD5Util.md5EncodeWeb(des3));
    		if(MD5Util.md5EncodeWeb(des3).equalsIgnoreCase(md5)){
    			System.out.println("MD5对比成功");
    		}
//    	 	System.out.println(encryptThreeDESECB(date, key));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    /**
     * 对map中的事件 url值进行加密,事件目前包含双击和单击
     * @param request
     * @param attributesMap
     * @throws Exception 
     */
	public static Map encryptEventUrl(ServletRequest request, Map attributesMap) throws Exception {
		//如果包含双击事件
		if(attributesMap.containsKey(ISystemConstant.EVENT_DBLCLICK)){
			attributesMap.put(ISystemConstant.EVENT_DBLCLICK, replacePlaintextUrl(request,(String)attributesMap.get(ISystemConstant.EVENT_DBLCLICK)));
		}
		//如果包含单击事件
		if(attributesMap.containsKey(ISystemConstant.EVENT_CLICK)){
			attributesMap.put(ISystemConstant.EVENT_CLICK, replacePlaintextUrl(request,(String)attributesMap.get(ISystemConstant.EVENT_CLICK)));
		}
		//如果包含变更事件
		if(attributesMap.containsKey(ISystemConstant.EVENT_ON_CHANGE)){
			attributesMap.put(ISystemConstant.EVENT_ON_CHANGE, replacePlaintextUrl(request,(String)attributesMap.get(ISystemConstant.EVENT_ON_CHANGE)));
		}
		return attributesMap;
		
	}
	/**
	 * 替换明文url为密文url
	 * @param request 
	 * @param eventBody 明文url
	 * @return
	 * @throws Exception 
	 */
	private static String replacePlaintextUrl(ServletRequest request, String eventBody) throws Exception {
	   String firstRegex = "'(.+?)'";
	   String retVal = eventBody;
	   Pattern firstwp = Pattern.compile(firstRegex,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
	   Matcher matcher = firstwp.matcher(eventBody);   
	   while( matcher.find()){
	    	for(int i=1;i<=matcher.groupCount();i++){
	    		String checkVal = matcher.group(i);
				if(checkVal!=null){
	    			//如果包含/，则认为是url
	    			if(StringHelper.findStrNum(checkVal, "/")>0){
	    				retVal = StringHelper.replaceAll(retVal, checkVal, encryptUrl((HttpServletRequest) request, checkVal)).toString();
	    			}
	    		}
	    	}

	    }

		return retVal;
	}
    
}
